#pragma once

#include "deviceManager.hpp"
#include <algorithm>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

class PollDeviceServer {
private:
    std::vector<std::size_t> _pollDeviceList;
    std::condition_variable _cv;
    std::mutex _mutex;

    std::shared_ptr<DeviceManager> _device;

private:
    void pollDeviceThread(void) {
        while (true) {
            {
                std::unique_lock<std::mutex> _lock(_mutex);
                _cv.wait(_lock, [&] { return !_pollDeviceList.empty(); });
            }
            for (const auto &id : _pollDeviceList) {
                auto device = _device->findDevice(id);
                if (!device) {
                    std::cerr << "bad device" << std::endl;
                    continue;
                }
                device->readNextPoint();
                std::this_thread::sleep_for(std::chrono::milliseconds(200));
            }
        }
    }

public:
    PollDeviceServer(std::shared_ptr<DeviceManager> d)
        : _device(d){};

    void push_if(std::size_t id) {
        std::lock_guard<std::mutex> _lock(_mutex);

        if (std::find_if(_pollDeviceList.begin(), _pollDeviceList.end(), [id](std::size_t i) { return i == id; }) == _pollDeviceList.end()) {
            _pollDeviceList.emplace_back(id);
        }

        _cv.notify_one();
    }

    void pop_if(std::size_t id) {
        std::lock_guard<std::mutex> _lock(_mutex);
        _pollDeviceList.erase(std::remove_if(_pollDeviceList.begin(), _pollDeviceList.end(), [id](std::size_t i) { return i == id; }), _pollDeviceList.end());
    }

    void start(void) {
        std::thread(&PollDeviceServer::pollDeviceThread, this).detach();
    }
};
